import CodeView from '../../../shared/components/CodeView';
import CodeBlock from '../../../shared/components/CodeBlock';
import Example from '../../../shared/components/Example';
import Blockquote from '../../../shared/components/Blockquote';
import StylingHooksTable from '../../../shared/components/StylingHooksTable';
import MobileTabs, { MobileTabGroup, NestedMobileStacked } from './mobile-stack/';
import { TabsDefault, TabsOverflow, TabsOverflowIcons, TabsWithNestedScopedTabs, TabsWithCards, TabsMedium, TabsLarge, TabsWithError, TabsWithHeading } from '../tabs/base/example';
import { SubTabSet, TabWithFocus, TabsWithBorders, TabActionOverflow, StatusTab, OverflowSubtabs } from '../tabs/sub-tabs/example';
import * as SubTabs from '../tabs/sub-tabs/example';
import VerticalTabs from '../vertical-tabs/base/example';
import { getDisplayElementById } from '../../shared/helpers';

<div className="doc lead">
  Tabs keeps related content in a single container that is shown and hidden
  through navigation.
</div>

<CodeView exampleOnly demoStyles="height: 200px;">
  <TabsDefault />
</CodeView>

## About Tabs

The default tab set style encapsulates everything that is underneath it without enclosing it visually. Because tab sets can be nested, pay close attention to the markup. They are constructed to prevent styles from leaking from parent tab sets into child tab sets.

### Implementation

#### Markup

The following markup is crucial for Accessibility

- Selected tab’s anchor has `aria-selected="true"`, all other tabs’ anchors have `aria-selected="false"`
- Selected tab’s anchor has `tabindex="0"`, all other tabs have `tabindex="-1"`
- Each tab’s anchor has an `aria-controls` attribute whose value is the id of the associated `<div role="tabpanel">`
- Each tab panel has an `aria-labelledby` attribute whose value is the id of its associated `<a role="tab">`

#### Keyboard Interactions

- Arrow keys, when focus is on a selected tab, cycle selection to the next or previous tab
- Tab key, when focus is before the tab list, moves focus to the selected tab
- Tab key, when focus is on selected tab, moves focus into the selected tab’s associated tab panel or to the next focusable element on the page if that panel has no focusable elements
- Shift+Tab keys, when focus is on first element in a tab panel, moves focus back to the selected tab

#### JavaScript Needs

The active tab has two markup requirements:

- The `.slds-active` class should be placed on the `li` with `.slds-tabs_{variant}__item`.
- The corresponding `.slds-tabs_{variant}__content` container receives `.slds-show`.
- In order to achieve the focus state styling, apply `.slds-has-focus` to the parent `li`.

Inactive `.slds-tabs_{variant}__content` containers receive `.slds-hide`.

When the user clicks a different tab, move the `.slds-active` class and toggle the `.slds-hide`/`.slds-show` classes.

### Accessibility

Tabbed UIs have three parts with specific **ARIA** role requirements:

- The tab list, which should have `role="tablist"`
- The tabs in that list, which should each be an `<a role="tab">` anchor wrapped in a `<li role="presentation">` list item
- The tab panels, which display each tab’s content and should each have `role="tabpanel"`

## Base

<Example title="Tabs Base">
  <CodeView demoStyles="height: 200px;">
    <TabsDefault />
  </CodeView>
</Example>

## Size Modifiers

Tabs come with three size modifiers: default, medium, and large. Each size step will gradually increase the typography. Add the modifier class `slds-tabs_medium` or `slds-tabs_large` to the `slds-tabs_default` element.

### Medium

<Example title="Tabs with Medium sizing modifier">
  <CodeView>
    <TabsMedium />
  </CodeView>
</Example>

### Large

<Example title="Tabs with Large sizing modifier">
  <CodeView>
    <TabsLarge />
  </CodeView>
</Example>

## With Header

<Example title="Tabs with Header">
  <CodeView demoStyles="height: 200px;">
    <TabsWithHeading/>
  </CodeView>
</Example>

<Blockquote type="a11y" header="Accessibility Note">
  <p>
    The header can be visually hidden but still accessible to screen readers by applying <code>slds-assistive-text</code> to the <code>slds-tabs_default__header</code> element.
  </p>
</Blockquote>

### Medium

<Example title="Tabs with Medium Size Header">
  <CodeView demoStyles="height: 200px;">
    <TabsMedium withHeader showHeader/>
  </CodeView>
</Example>

### Large

<Example title="Tabs with Large Size Header">
  <CodeView demoStyles="height: 200px;">
    <TabsLarge withHeader showHeader/>
  </CodeView>
</Example>

## With Overflow

The overflow tab style is provided as a tab item type that acts as a menu component and appears as a tab item. It could contain those tab items that don't all fit in a horizontal orientation.

<Example title="Tabs Overflowing">
  <CodeView demoStyles="height: 200px;">
    <TabsOverflow />
  </CodeView>
</Example>

<Blockquote type="a11y" header="Accessibility Note">
  <p>
    The overflow tab should have a <code>role="tab"</code> to ensure screen readers properly announce it as a tab, keeping it consistent with the number of tabs visible to sighted users.
  </p>
</Blockquote>

<Blockquote type="note" header="Implementation Guidelines">
  <p>
    The <code>slds-dropdown__list</code> element requires a
    <code>slds-dropdown_length-with-icon-10</code> class, where 10 is the maximum number of
    items that will be visible before having to scroll.
  </p>
</Blockquote>

## With Icon

Icons can be used with tabs to help users differentiate among them.

<Example title="Tabs With Icons">
  <CodeView demoStyles="height: 200px;">
    <TabsOverflowIcons />
  </CodeView>
</Example>

## With Error

An icon can be used to communicate when a tab contains a validation error that needs attention.

<Example title="Tabs With Icons">
  <CodeView demoStyles="height: 200px;">
    <TabsWithError />
  </CodeView>
</Example>

## With Nested Scoped Tabs

If nesting tabs within tabs, the second set should be rendered as [Scoped Tabs](/components/scoped-tabs) to help differentiate between tab sets.

<Example title="Tabs with Nested Scoped Tabs">
  <CodeView demoStyles="height: 200px;">
    <TabsWithNestedScopedTabs />
  </CodeView>
</Example>

## Subtabs

Subtabs are used to provide an additional level of navigation below the [Global Navigation](/components/global-navigation) Tab Bar. Use these tabs when users need to work across multiple sub-pages within a single navigation item.

<CodeView demoStyles="height: 100px;">{getDisplayElementById(SubTabs.default)}</CodeView>

### Expected Behavior

- The first tab within the Subtab Bar is always the default content for the parent navigation item. To differentiate this tab from other sub-navigation tabs, this tab cannot be closed.
- When opening a navigation item for the first time, the default sub-navigation tab can be assumed; don’t show the Subtab Bar.
  - When opening the first additional sub-navigation tab, a new tab bar is inserted containing both the default tab and the new sub-navigation tab.
- All subtabs are closed when the parent navigation item is closed.
- Subtabs can optionally include a tab menu for additional controls.

### With Focus

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'subtabs-has-focus')}
</CodeView>

### With Borders

To add borders on either side of the subtab, add the classes `slds-border_right` and `slds-border_left`, as needed, to the `<li>` with class `slds-sub-tabs__item`.

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'subtabs-borders')}
</CodeView>

### With Tab Actions

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'subtabs-menu')}
</CodeView>

### Status Options

#### Unsaved Tab

Unsaved tabs receive a blue asterisk on the tab.

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'subtabs-unsaved')}
</CodeView>

<Blockquote header="Additional Tag for Accessibility" type="a11y">
  <p>
    In order to inform screen readers of the unsaved state, an <code>&lt;abbr&gt;</code> tag
    is used to render the asterisk. The <code>title</code> attribute and <code>aria-label</code> should
    read <b>"Tab Not Saved"</b>.
  </p>
</Blockquote>

<CodeBlock toggleCode={false}>
  <abbr
    className="slds-indicator_unsaved"
    title="Tab Not Saved"
    aria-label="Tab Not Saved"
  >
    *
  </abbr>
</CodeBlock>

#### Communicating Status to Screen Readers

The following examples of subtab status updates should all employ the same technique to communicate that update to users of assistive technology, who would be otherwise unaware of that status change.

You should use a single hidden ARIA live region for the entire subtabs block, the contents of which gets updated each time a subtab changes its status. The contents should contain a description of the status level and the name of the tab the status change event occurred in. The markup would look something like:

<CodeBlock toggleCode={false}>
  <div className="slds-assistive-text" aria-live="polite">
    ...
  </div>
</CodeBlock>

Upon clearing the status on a given tab, you should clear the message from the live region.

#### Unread Tab

Unread tabs receive a red dot on the tab.

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'unread')}
</CodeView>

<Blockquote header="Accessibility" type="a11y">
  <p>
    In order to inform screen readers of new activity in a tab, 2 things should
    occur.
  </p>
  <ol className="slds-list_ordered">
    <li>
      The <code>title</code> attribute and <code>aria-label</code> on the element that displays the red
      dot should read <b>"New Activity"</b>. This will update the text content of the
      tab to include the "New Activity" text: "New Activity Chat - Customer".
    </li>
    <li>
      The hidden live region as described above, should have its content updated
      to <b>"New Activity in Tab: [Tab Name Here]"</b> to alert the user of new
      activity in that particular subtab.
    </li>
  </ol>
</Blockquote>

<CodeBlock toggleCode={false}>
  <span
    aria-label="New Activity"
    className="slds-indicator_unread"
    title="New Activity"
    role="img"
  />
</CodeBlock>

<CodeBlock toggleCode={false}>
  <div className="slds-assistive-text" aria-live="polite">
    New activity in Tab: Chat - Customer
  </div>
</CodeBlock>

#### Unread and Unsaved Tab

Unread and unsaved tabs receive a blue asterisk with a red dot underneath. Be sure to check out the individual sections above for the Accessibility requirements.

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'unsaved')}
</CodeView>

<Blockquote header="Accessibility" type="a11y">
  <p>
    Don't forget to update the hidden live region with which subtab has new
    activity
  </p>
</Blockquote>

#### Warning Tab

When you wish to draw attention to a particular subtab because a warning about that tab has occurred, you can use the `slds-has-warning` class to change the background color and introduce a short pulsing animation to draw attention from the user.

The icon is updated to be the warning icon, to give an extra way to communicate the level of the status without relying on the use of color alone.

In this example we show that something inside the subtab is about to break a service level agreement in 30 seconds, and we wish to draw the users attention to it to take action.

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'warning')}
</CodeView>

<Blockquote header="Accessibility" type="a11y">
  <p>
    Update the hidden live region with a message that informs the user of the
    status level, the warning and the offending subtab{' '}
    <b>[level]: [message] in tab: [tab_name]</b>
  </p>
</Blockquote>

<CodeBlock toggleCode={false}>
  <div className="slds-assistive-text" aria-live="polite">
    Warning: SLA agreement in 30 seconds in tab: Chat - Customer
  </div>
</CodeBlock>

##### Unsaved Warning Tab

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'warning-unsaved')}
</CodeView>

##### Unread Warning Tab

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'warning-unread')}
</CodeView>

#### Error Tab

When you wish to draw attention to a particular subtab because an error or violation has occurred in that tab, you can use the `slds-has-error` class to change the background color and introduce a short pulsing animation to draw attention from the user.

The icon is updated to be the error icon, to give an extra way to communicate the level of the status without relying on the use of color alone.

In this example we show that something inside the subtab has broken an SLA agreement, and we wish to draw the users attention to it to take action.

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'error')}
</CodeView>

<Blockquote header="Accessibility" type="a11y">
  <p>
    Update the hidden live region with a message that informs the user of the
    status level, the error or violation and the offending subtab{' '}
    <b>[level]: [message] in tab: [tab_name]</b>
  </p>
</Blockquote>

<CodeBlock toggleCode={false}>
  <div className="slds-assistive-text" aria-live="polite">
    Violation: SLA agreement in tab: Chat - Customer
  </div>
</CodeBlock>

##### Unsaved Error Tab

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'error-unsaved')}
</CodeView>

##### Unread Error Tab

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'error-unread')}
</CodeView>

#### Success Tab

When you wish to draw attention to a particular subtab because a warning or violation has been cleared in the subtab, you can use the `slds-has-success` class to change the background color and introduce a short pulsing animation to draw attention from the user.

The icon is updated to be the success icon, to give an extra way to communicate the level of the status without relying on the use of color alone.

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'success')}
</CodeView>

<Blockquote header="Accessibility" type="a11y">
  <p>
    Update the hidden live region with a message that informs the user that the
    status level has been successfully cleared and the subtab it was cleared from{' '}
    <b>[level]: [message] in tab: [tab_name]</b>
  </p>
</Blockquote>

<CodeBlock toggleCode={false}>
  <div className="slds-assistive-text" aria-live="polite">
    Success: SLA agreement warning cleared in tab: Chat - Customer
  </div>
</CodeBlock>

##### Unsaved Success Tab

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'success-unsaved')}
</CodeView>

##### Unread Success Tab

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'success-unread')}
</CodeView>

### With Overflow Tab

Overflowing subtabs are contained in a More dropdown.

<CodeView demoStyles="height: 100px;">
  {getDisplayElementById(SubTabs.states, 'overflow-tabs')}
</CodeView>

#### Overflow Tab Open

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(SubTabs.states, 'overflow-tabs-open')}
</CodeView>

#### Unread Overflow Tab

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(SubTabs.states, 'unread-overflow-tabs-open')}
</CodeView>

#### Unsaved Overflow Tab

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(SubTabs.states, 'unsaved-overflow-tabs-open')}
</CodeView>

#### Unread and Unsaved Overflow Tab

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(SubTabs.states, 'unsaved-unread-overflow-tabs-open')}
</CodeView>

#### Success Overflow Tab

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(SubTabs.states, 'overflow-tabs-success')}
</CodeView>

#### Unread and Unsaved Success Overflow Tab

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(
    SubTabs.states,
    'overflow-tabs-success-unread-unsaved'
  )}
</CodeView>

#### Warning Overflow Tab

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(SubTabs.states, 'overflow-tabs-warning')}
</CodeView>

#### Unread and Unsaved Warning Overflow Tab

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(
    SubTabs.states,
    'overflow-tabs-warning-unread-unsaved'
  )}
</CodeView>

#### Error Overflow Tab

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(SubTabs.states, 'overflow-tabs-error')}
</CodeView>

#### Unread and Unsaved Error Overflow Tab

<CodeView demoStyles="height: 200px;">
  {getDisplayElementById(SubTabs.states, 'overflow-tabs-error-unread-unsaved')}
</CodeView>

## Vertical

To use vertical tabs, check out the [Vertical Tabs](../vertical-tabs) component.

<Example title="Tabs as Vertical">{VerticalTabs}</Example>

## As a Card

To style tabs as a card, add the class `slds-tabs_card` to the `<div>` with the class `slds-tabs_default`. See the following example for guidance on styling cards inside the tab panel content.

<Example title="Tabs as a Card">
  <CodeView demoStyles="height: 600px;">
    <TabsWithCards />
  </CodeView>
</Example>

## On Mobile

For mobile, tabs become stacked and act as buttons that drill in to see the tab's content.

Mobile tabs consist of two parts, the tabs, which are represented via buttons, and their associated panels. When clicking on one of the buttons, the associated panel will slide in from right-to-left.

<Blockquote header="Focus Management" type="a11y">
  <p>
    When a user selects a tab button, focus should be placed on the back button of
    the panel that slides into view. When the user clicks the back button, focus
    should be placed on the button that was just pressed.
  </p>
</Blockquote>

<Example title="Tabs Mobile Base">
  <CodeView>
    <MobileTabs />
  </CodeView>
</Example>

### Accessibility

**Visibility**

- The panels should have `aria-hidden=true` when they are not visible to ensure keyboard and screen reader users cannot access the content.
- The tabs should have `aria-hidden=true` when a panel is open to ensure keyboard and screen reader users cannot access the buttons.

**Focus Management**

When a user selects a tab button, focus should be placed on the back button of the panel that slides into view. When the user clicks the back button, focus should be placed on the button that was just pressed.

**Assistive Text**

The title and assistive text for the panel's back button text should read "Collapse \$&123;heading text&125;” so it stays contextual to the tab that was clicked on.

### Panel Open

When clicking a tab button, the entire view changes and is replaced with the "content" of that tab inside of a panel. This includes a back button on the top left of the screen to go back to the view with the tabs.

<Example title="Tabs Mobile Drilled-in">
  <CodeView>
    <MobileTabs visiblePanelIdx={0} isStatic />
  </CodeView>
</Example>

### Adjacent Tab Sets

When there are two or more immediately adjacent tab sets on mobile, use the `slds-tabs_mobile__group` class to adjust the styling to make them appear as if they're part of one master list. Semantically, they are still two separate lists.

<Example title="Tabs Mobile Adjacent Stacked">
  <CodeView>
    <MobileTabGroup>
      <MobileTabs isStatic />
      <MobileTabs isStatic startingIdx={3} />
    </MobileTabGroup>
  </CodeView>
</Example>

### Nested Tab Sets

<Example title="Tabs Mobile Nested">
  <CodeView demoStyles="height: 300px;">
    <NestedMobileStacked />
  </CodeView>
</Example>

## Styling Hooks Overview

<StylingHooksTable name="tabs" type="component" />
